using System;
using System.IO;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

/*
 *  QAP algo
 *  Generate m initial
 *	Initialize trail
 *		For imax:
 *			for each ant:
 *				modify soln using pheromone trail
 *				apply local search to modified
 *				associate new start to this ant using intensification
 *			update trail
 *			diversify
 */

namespace AntsMap
{


		/// <summary>
		/// Summary description for Form1.
		/// </summary>
		public class Form1 : System.Windows.Forms.Form
		{
			private CostMap costmap;
			private Point[,] nodes;

            private bool pausing;
			public int[,] ballarray = new int[20,5];  //r,c  ... 20 rows, 20 columns
			public string[] colours = new string[22];
			public int g1=1;
			public int g2=200;
			public Bitmap bmp;
            private DateTime start;
            

            private Solver solver;
			private int[,] tempsol;
			private int[,] bestsol;

			private System.Windows.Forms.Timer timer1;
            private System.Windows.Forms.MainMenu mainMenu1;
			private System.Windows.Forms.StatusBar statusBar1;
            private System.Windows.Forms.TextBox textBox1;
            private ToolStrip toolStrip1;
            private ToolStripComboBox toolStripComboBox1;
            private ToolStripButton toolStripButtonStop;
            private ToolStripButton toolStripButtonStart;
            private ToolStripButton toolStripButtonPause;
            private OpenFileDialog openFileDialog1;
            private MenuStrip menuStrip1;
            private ToolStripMenuItem fileToolStripMenuItem;
            private ToolStripMenuItem openToolStripMenuItem;
            private ToolStripMenuItem aboutToolStripMenuItem;
            private ProgressBar progressBar1;
            private StatusBarPanel statusBarPanel1;
            private StatusBarPanel statusBarPanel2;
			private System.ComponentModel.IContainer components;

			public Form1()
			{
				//
				// Required for Windows Form Designer support
				//
				InitializeComponent();
				
                // TODO will crash if more than 16 elements-run out of colors
                colours[0]="Green";
				colours[1]="Red";
				colours[2]="Blue";
				colours[3]="Black";
				colours[4]="Yellow";
				colours[5]="Crimson";
				colours[6]="Gold";
				colours[7]="Green";
				colours[8]="Magenta";
				colours[9]="Aquamarine";
				colours[10]="Brown";
				colours[11]="Red";
				colours[12]="DarkBlue";
				colours[13]="Brown";
				colours[14]="Red";
				colours[15]="DarkBlue";
                colours[16] = "Green";
                colours[17] = "Red";
                colours[18] = "Blue";
                colours[19] = "Black";
                colours[20] = "Yellow";
                colours[21] = "Green";
        
				//
				// TODO: Add any constructor code after InitializeComponent call
				//
                start = new DateTime();
                pausing = false;
                // TODO if testproblem.txt isn't present it will crash.  
				costmap = new CostMap();
				costmap.Testfile = "testproblem.txt";
				costmap.BuildCostMap();

                InitializeFromCostmap();

			}

			/// <summary>
			/// Clean up any resources being used.
			/// </summary>

			protected override void Dispose( bool disposing )
			{
				if( disposing )
				{
					if (components != null) 
					{
						components.Dispose();
					}
				}
				base.Dispose( disposing );
			}

			#region Windows Form Designer generated code

			/// <summary>
			/// Required method for Designer support - do not modify
			/// the contents of this method with the code editor.
			/// </summary>

			private void InitializeComponent()
			{
                this.components = new System.ComponentModel.Container();
                System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
                this.timer1 = new System.Windows.Forms.Timer(this.components);
                this.mainMenu1 = new System.Windows.Forms.MainMenu(this.components);
                this.statusBar1 = new System.Windows.Forms.StatusBar();
                this.textBox1 = new System.Windows.Forms.TextBox();
                this.toolStrip1 = new System.Windows.Forms.ToolStrip();
                this.toolStripComboBox1 = new System.Windows.Forms.ToolStripComboBox();
                this.toolStripButtonStart = new System.Windows.Forms.ToolStripButton();
                this.toolStripButtonPause = new System.Windows.Forms.ToolStripButton();
                this.toolStripButtonStop = new System.Windows.Forms.ToolStripButton();
                this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
                this.menuStrip1 = new System.Windows.Forms.MenuStrip();
                this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
                this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
                this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
                this.progressBar1 = new System.Windows.Forms.ProgressBar();
                this.statusBarPanel1 = new System.Windows.Forms.StatusBarPanel();
                this.statusBarPanel2 = new System.Windows.Forms.StatusBarPanel();
                this.toolStrip1.SuspendLayout();
                this.menuStrip1.SuspendLayout();
                ((System.ComponentModel.ISupportInitialize)(this.statusBarPanel1)).BeginInit();
                ((System.ComponentModel.ISupportInitialize)(this.statusBarPanel2)).BeginInit();
                this.SuspendLayout();
                // 
                // timer1
                // 
                this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
                // 
                // statusBar1
                // 
                this.statusBar1.Location = new System.Drawing.Point(0, 272);
                this.statusBar1.Name = "statusBar1";
                this.statusBar1.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {
            this.statusBarPanel1,
            this.statusBarPanel2});
                this.statusBar1.ShowPanels = true;
                this.statusBar1.Size = new System.Drawing.Size(425, 25);
                this.statusBar1.TabIndex = 0;
                // 
                // textBox1
                // 
                this.textBox1.BackColor = System.Drawing.SystemColors.Control;
                this.textBox1.Dock = System.Windows.Forms.DockStyle.Right;
                this.textBox1.ForeColor = System.Drawing.SystemColors.InfoText;
                this.textBox1.Location = new System.Drawing.Point(425, 0);
                this.textBox1.Multiline = true;
                this.textBox1.Name = "textBox1";
                this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
                this.textBox1.Size = new System.Drawing.Size(206, 297);
                this.textBox1.TabIndex = 1;
                // 
                // toolStrip1
                // 
                this.toolStrip1.BackColor = System.Drawing.SystemColors.Control;
                this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.toolStripComboBox1,
            this.toolStripButtonStart,
            this.toolStripButtonPause,
            this.toolStripButtonStop});
                this.toolStrip1.Location = new System.Drawing.Point(0, 24);
                this.toolStrip1.Name = "toolStrip1";
                this.toolStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
                this.toolStrip1.Size = new System.Drawing.Size(425, 25);
                this.toolStrip1.TabIndex = 2;
                this.toolStrip1.Text = "toolStrip1";
                // 
                // toolStripComboBox1
                // 
                this.toolStripComboBox1.BackColor = System.Drawing.SystemColors.Window;
                this.toolStripComboBox1.Items.AddRange(new object[] {
            "Stupid Brute",
            "2-Exchange Local",
            "Simulated Annealing",
            "Ants"});
                this.toolStripComboBox1.Name = "toolStripComboBox1";
                this.toolStripComboBox1.Size = new System.Drawing.Size(121, 25);
                this.toolStripComboBox1.Text = "Select a solver";
                this.toolStripComboBox1.ToolTipText = "Select the solver algorithm";
                // 
                // toolStripButtonStart
                // 
                this.toolStripButtonStart.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
                this.toolStripButtonStart.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButtonStart.Image")));
                this.toolStripButtonStart.ImageTransparentColor = System.Drawing.Color.Magenta;
                this.toolStripButtonStart.Name = "toolStripButtonStart";
                this.toolStripButtonStart.Size = new System.Drawing.Size(23, 22);
                this.toolStripButtonStart.Text = "Start ";
                this.toolStripButtonStart.Click += new System.EventHandler(this.toolStripButtonStart_Click);
                // 
                // toolStripButtonPause
                // 
                this.toolStripButtonPause.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
                this.toolStripButtonPause.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButtonPause.Image")));
                this.toolStripButtonPause.ImageTransparentColor = System.Drawing.Color.Magenta;
                this.toolStripButtonPause.Name = "toolStripButtonPause";
                this.toolStripButtonPause.Size = new System.Drawing.Size(23, 22);
                this.toolStripButtonPause.Text = "Pause";
                this.toolStripButtonPause.Click += new System.EventHandler(this.toolStripButtonPause_Click);
                // 
                // toolStripButtonStop
                // 
                this.toolStripButtonStop.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
                this.toolStripButtonStop.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButtonStop.Image")));
                this.toolStripButtonStop.ImageTransparentColor = System.Drawing.Color.Magenta;
                this.toolStripButtonStop.Name = "toolStripButtonStop";
                this.toolStripButtonStop.Size = new System.Drawing.Size(23, 22);
                this.toolStripButtonStop.Text = "Stop";
                this.toolStripButtonStop.Click += new System.EventHandler(this.toolStripButtonStop_Click);
                // 
                // openFileDialog1
                // 
                this.openFileDialog1.FileName = "openFileDialog1";
                // 
                // menuStrip1
                // 
                this.menuStrip1.BackColor = System.Drawing.SystemColors.Control;
                this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.fileToolStripMenuItem,
            this.aboutToolStripMenuItem});
                this.menuStrip1.Location = new System.Drawing.Point(0, 0);
                this.menuStrip1.Name = "menuStrip1";
                this.menuStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
                this.menuStrip1.Size = new System.Drawing.Size(425, 24);
                this.menuStrip1.TabIndex = 3;
                this.menuStrip1.Text = "menuStrip1";
                // 
                // fileToolStripMenuItem
                // 
                this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.openToolStripMenuItem});
                this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
                this.fileToolStripMenuItem.Size = new System.Drawing.Size(35, 20);
                this.fileToolStripMenuItem.Text = "File";
                // 
                // openToolStripMenuItem
                // 
                this.openToolStripMenuItem.Name = "openToolStripMenuItem";
                this.openToolStripMenuItem.Size = new System.Drawing.Size(100, 22);
                this.openToolStripMenuItem.Text = "Open";
                this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click);
                // 
                // aboutToolStripMenuItem
                // 
                this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
                this.aboutToolStripMenuItem.Size = new System.Drawing.Size(48, 20);
                this.aboutToolStripMenuItem.Text = "About";
                this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
                // 
                // progressBar1
                // 
                this.progressBar1.Location = new System.Drawing.Point(267, 24);
                this.progressBar1.Name = "progressBar1";
                this.progressBar1.Size = new System.Drawing.Size(158, 23);
                this.progressBar1.TabIndex = 4;
                // 
                // statusBarPanel1
                // 
                this.statusBarPanel1.BorderStyle = System.Windows.Forms.StatusBarPanelBorderStyle.None;
                this.statusBarPanel1.Name = "statusBarPanel1";
                this.statusBarPanel1.Width = 250;
                // 
                // statusBarPanel2
                // 
                this.statusBarPanel2.BorderStyle = System.Windows.Forms.StatusBarPanelBorderStyle.None;
                this.statusBarPanel2.Name = "statusBarPanel2";
                this.statusBarPanel2.Width = 150;
                // 
                // Form1
                // 
                this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                this.ClientSize = new System.Drawing.Size(631, 297);
                this.Controls.Add(this.progressBar1);
                this.Controls.Add(this.toolStrip1);
                this.Controls.Add(this.menuStrip1);
                this.Controls.Add(this.statusBar1);
                this.Controls.Add(this.textBox1);
                this.Menu = this.mainMenu1;
                this.Name = "Form1";
                this.Text = "Ants MAP";
                this.Load += new System.EventHandler(this.Form1_Load);
                this.toolStrip1.ResumeLayout(false);
                this.toolStrip1.PerformLayout();
                this.menuStrip1.ResumeLayout(false);
                this.menuStrip1.PerformLayout();
                ((System.ComponentModel.ISupportInitialize)(this.statusBarPanel1)).EndInit();
                ((System.ComponentModel.ISupportInitialize)(this.statusBarPanel2)).EndInit();
                this.ResumeLayout(false);
                this.PerformLayout();

			}
			#endregion

			/// <summary>
			/// The main entry point for the application.
			/// </summary>

			[STAThread]
			static void Main() 
			{
                Application.EnableVisualStyles();
				Application.Run(new Form1());
			}


            private void InitializeFromCostmap()
            {
                // Temporary and best solutions
                tempsol = new int[costmap.Elements, costmap.Dimension];
                bestsol = new int[costmap.Elements, costmap.Dimension];
                // Create a handy array of points to draw our points and circles
                nodes = new Point[costmap.Elements, costmap.Dimension];

                for (int i = 0; i < costmap.Elements; i++)
                {
                    for (int j = 0; j < costmap.Dimension; j++)
                    {
                        int yoffset = 70;
                        int xoffset = 20;
                        nodes[i, j] = new Point(100 * j + xoffset, 50 * i + yoffset);
                    }
                }

                for (int i = 0; i < costmap.Elements; i++)
                {
                    for (int j = 0; j < costmap.Elements; j++)
                    {
                        for (int k = 0; k < costmap.Elements; k++)
                        {
                            this.textBox1.AppendText("Cost of " + i.ToString() + j.ToString() + k.ToString() + " -- " + Convert.ToString(costmap.Cost(i, j, k)) + "\r\n");
                        }
                    }
                }
                /*
                 * show that these solutions are good
                SolutionPermuter sp = new SolutionPermuter( costmap.Dimension, costmap.Elements);
                int[,] sol = sp.GenerateSolution( );
                for( int i = 0; i<costmap.Elements;i++)
                {
                    string soln = "";
                    for(int j=0;j<costmap.Dimension;j++)
                    {
                        soln += sol[i,j].ToString();
                    }
                    this.textBox1.AppendText( soln );
                }
                */
                //this.statusBar1.Text = "This problem has " + costmap.Dimension + " dimensions and " + costmap.Elements + " elements";
                this.statusBarPanel1.Text = "This problem has " + costmap.Dimension + " dimensions and " + costmap.Elements + " elements";
            }




            // Happens every tick of the clock
			private void timer1_Tick(object sender, System.EventArgs e)
			{
				//SolutionPermuter sp = new SolutionPermuter( costmap.Elements, costmap.Dimension);
				//this.tempsol = sp.GenerateSolution();
                if (solver.Optimal == false)
                {
                    tempsol = solver.SolveStep();
                    
                    if( this.progressBar1.Value < this.progressBar1.Maximum)
                        this.progressBar1.Value = solver.GetIteration();

                    TimeSpan duration = System.DateTime.Now - this.start;
                    statusBarPanel2.Text = "Milliseconds: " + duration.TotalMilliseconds.ToString();
                    textBox1.AppendText( solver.Message() + "\r\n");  // Give the solver a chance to tell us something
                    this.Refresh(); //force repaint of window
                }
                else
                {
                    //TODO draw the last best soln.  This here isn't working.
                    tempsol = solver.BestSolution();
                    this.Refresh();
                    this.progressBar1.Value = 0;
                    timer1.Stop();
                    pausing = false;
                    textBox1.AppendText("The best cost is " + solver.BestCost().ToString() + "\r\n");
                }
			}
 
			//Called from timer event when window needs redrawing
			protected override void OnPaint(PaintEventArgs e)
			{
				if( timer1.Enabled == true )
				{
					bmp = new Bitmap(ClientSize.Width,ClientSize.Height, e.Graphics);
					Graphics bmpGraphics = Graphics.FromImage(bmp);
					// draw here
					Pen nodepen = new Pen( Color.Blue );
					int rows = costmap.Elements;
					int cols = costmap.Dimension;
					int radius = 5;
					
					// Draw ellipses to represent the assignment nodes using the nodes[] array
					for( int i = 0 ; i < rows; i++ )
					{
						for( int j = 0; j < cols; j++ )
						{
							bmpGraphics.DrawEllipse( nodepen, nodes[i,j].X, nodes[i,j].Y, radius, radius);
						}
					}
                    this.textBox1.AppendText("Best Cost: " + solver.BestCost() +"\r\n");
					//this.textBox1.AppendText( "Current cost: " + costmap.Cost(tempsol).ToString() + "\r\n");

					// Pull out the points from the nodes[] array that we wish to connect.  There will be #elems such of these.
					Point[] points = new Point[ cols ];		
					for( int i = 0 ; i < rows ; i++ )
					{	
						for( int j=0; j<cols; j++)
						{	
							points[j] = nodes[ tempsol[i,j],j];
						}
						bmpGraphics.DrawLines( new Pen( Color.FromName(colours[i])), points );
					}
				
					e.Graphics.DrawImageUnscaled(bmp, 0, 0);
					bmpGraphics.Dispose();
					bmp.Dispose();
				}
			}
           
			

			private void Form1_Load(object sender, System.EventArgs e)
			{
			
			}

            private void toolStripContainer1_ContentPanel_Load(object sender, EventArgs e)
            {

            }

            private void toolStripButtonStop_Click(object sender, EventArgs e)
            {
                this.timer1.Stop();
                this.progressBar1.Value = 0;
                this.pausing = false;
            }

            private void toolStripButtonStart_Click(object sender, EventArgs e)
            {
                if (this.pausing == false)
                {
                    // this means we're really starting, need to pick a solver
                    start = System.DateTime.Now;
                    
                    SolutionPermuter sp = new SolutionPermuter( costmap.Elements, costmap.Dimension);
                    this.tempsol = sp.GenerateSolution();
                    this.progressBar1.Value = 0;
                    // Based on what's selected in the combo box, initialize a Solver and run.
                    switch (toolStripComboBox1.SelectedIndex)
                    {
                        case 0:
                            solver = new SolverBrute(tempsol, costmap.Dimension, costmap.Elements, costmap, 1000);
                            pausing = true;
                            timer1.Start();
                            break;
                        case 1:
                            solver = new Solver2Exchange(tempsol, costmap.Dimension, costmap.Elements, costmap, 100);
                            pausing = true;
                            timer1.Start();
                            break;
                        case 2:
                            solver = new SolverAnnealing(tempsol, costmap.Dimension, costmap.Elements, costmap );
                            pausing = true;
                            timer1.Start();
                            this.progressBar1.Maximum = solver.GetMaxIteration();
                            break;
                        case 3:
                            solver = new SolverACO(tempsol, costmap.Dimension, costmap.Elements, costmap, 10);
                            pausing = true;
                            timer1.Start();
                            this.progressBar1.Maximum = solver.GetMaxIteration();
                            break;
                        default:
                            this.textBox1.AppendText("Select a solver first!\r\n");
                            break;
                    }
                }
                else
                {
                    start = System.DateTime.Now;
                    timer1.Start();
                }
            }

            private void toolStripButtonPause_Click(object sender, EventArgs e)
            {
                this.timer1.Stop();
                this.pausing = true;
            }

            private void openToolStripMenuItem_Click(object sender, EventArgs e)
            {
                Stream file;
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    if ((file = openFileDialog1.OpenFile()) != null)
                    {
                        costmap.Testfile = openFileDialog1.FileName;
                        costmap.BuildCostMap();
                        InitializeFromCostmap();
                        this.textBox1.AppendText("Loaded " + Path.GetFileName(costmap.Testfile) + "\r\n");
                        // Resize the window based on how many elements the new problem has
                        // The 70 + 120 is the toolbar offset plus a general "spaciousness" estimate
                        this.Height = costmap.Elements * (nodes[1, 0].Y - nodes[0, 0].Y) + (70+120);
                    }
                }
            }

            private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
            {
                AboutForm a = new AboutForm();
                a.ShowDialog();
            }
		}
	


}
